Data cleaning

There are a bunch of small inconsistencies that come with manual data entry that need to be corrected prior to analysis.

Checklist:

# Gathers dataset to long format before cleaning up, creates species column
long.comp <- gather(waps.comp, key = "species", value = "cover", -c(1:7))
# Removes year labels from species column
spec <- gsub("X\\d\\d\\.*", "", long.comp$species)
# Grabs the first two digits from the species column to make a "year" column
yr <- gsub('\\.', "", long.comp$species)
yr <- gsub("X", "20", yr)
yr <- gsub("[[:alpha:]]+0?", "", yr)
# Reassigns species variable
long.comp$species <- spec
# Attaches year variable
long.comp <- cbind(long.comp, year = as.numeric(yr))
# Lowercase names for dataset
names(long.comp) <- c("plot", "block", "subblock",
                      "water", "spcomp", "fertilization",
                      "clipping", "species", "cover", "year")
# Assigns all NA cover values to zero
long.comp$cover[is.na(long.comp$cover)] <- 0
# Reassigns species names to standardized names in the waps.specs dataset
for(i in waps.specs$Species){
  long.comp$species <- gsub(paste(i, "$", sep = ""), waps.specs$Newval[waps.specs$Species == i], long.comp$species)
}

After cleaning, we now have two separate dataframes, one that corresponds to different plot treatments/labels and another that corresponds to species abundances:

head(comp.attr)[,1:10]
head(comp.wide)[,1:10]
     aegilops ag.big ag.small amsinckia avena big.leaf.dandelion bindweed bro.carinatus bro.hordeaceous bro.madritensis
[1,]        0      0        0         0  12.5                  0        0             0             2.5               0
[2,]        0      0        0         0  12.5                  0        0             0             2.5               0
[3,]        0      0        0         0  25.0                  0        0             0             0.0               0
[4,]        0      0        0         0  75.0                  0        0             0             0.0               0
[5,]        0      0        0         0  35.0                  0        0             0             0.0               0
[6,]        0      0        0         0  25.0                  0        0             0             0.0               0

The species matrix contains a total of 50 unique species. The full list is provided below:

colnames(comp.wide)
 [1] "aegilops"               "ag.big"                 "ag.small"               "amsinckia"              "avena"                 
 [6] "big.leaf.dandelion"     "bindweed"               "bro.carinatus"          "bro.hordeaceous"        "bro.madritensis"       
[11] "bro.diandrus"           "bunchgrass"             "cap.bur"                "centaurea"              "con.arv"               
[16] "conyza"                 "elymus"                 "epilobium.brach"        "erodium.moschatum"      "galium"                
[21] "geranium"               "gumplant"               "helianthus"             "hordeum.sp"             "italian.thistle"       
[26] "kickxia.elatine"        "lactuca.serriola"       "leymus"                 "lolium"                 "lotus"                 
[31] "lupinus"                "melilotus"              "milk.thistle"           "mustard"                "nassella"              
[36] "oats"                   "orchard.grass"          "phalaris.sp"            "poa"                    "redmaid"               
[41] "senecio"                "taeniatherum"           "tarweed"                "thistle"                "tragopogon.porrifolius"
[46] "trifolium"              "unk.thistle"            "veronica"               "vicia"                  "vulpia"                
sum(is.na(long.comp$year))
[1] 0

Ordination analysis

unique(ord.att$clip)
[1] "none"
onegroup_trts = c("annuals", "WAPS", "Natives")
multigroup_trts = c("natives+WAPS+annuals", "annuals+natives", "WAPS+annuals", "WAPS+natives", "Centaureasolstitialis+WAPS+annuals")
onespec_trts = unique(comp.attr$sp.trt)[!unique(comp.attr$sp.trt) %in% c(onegroup_trts, multigroup_trts)]
selected.trts <- c(onegroup_trts, multigroup_trts)
selected.clips <- c("none")
selected.fert <- c("none")
selected.water <- c("control-2nd") 
ord.mat <- comp.wide[comp.attr$water == selected.water &
                     comp.attr$sp.trt %in% selected.trts &
                     comp.attr$clip %in% selected.clips&
                     comp.attr$fert %in% selected.fert,]
ord.att <- comp.attr[comp.attr$water == selected.water &
                     comp.attr$sp.trt %in% selected.trts &
                     comp.attr$clip %in% selected.clips &
                     comp.attr$fert %in% selected.fert,]
expect_true(nrow(ord.att) == nrow(ord.mat))
# A number of rows have no recorded live plants (not s)
ord.att <- ord.att[rowSums(ord.mat) != 0, ]
ord.mat <- ord.mat[rowSums(ord.mat) != 0, ]
ord.mat <- sqrt(ord.mat)
distmat <- vegdist(ord.mat)
WAPS.mds <- metaMDS(distmat, try = 5, trymax = 50, trace = F)
MDS_xy <- cbind(data.frame(ord.att), data.frame(X = WAPS.mds$points[,1], Y = WAPS.mds$points[,2]))
#WAPS.pca <- prcomp(ord.mat)
#PCA_xy <- cbind(data.frame(ord.att), data.frame(X = WAPS.pca$x[,1], Y = WAPS.pca$x[,2]))
library(ggplot2)
ggplot(MDS_xy, aes(X, Y, color = sp.trt, shape = clip)) + geom_point() + theme_bw() + facet_wrap(~year)

group_abund <- MDS_xy %>% gather(key = "group", value = "cover", annuals, bare, waps, natives, weeds) %>%
  replace_na(list(cover = 0)) 
ggplot(data = group_abund, 
       aes(x = year,
           y = cover,
           color = group)) +
  geom_point() + 
  facet_wrap(~sp.trt) +
  stat_smooth(method = "lm")

calcRateChange_bray <- function(comdf, comvar, abundvar, timevar){
  # Take dataframe,
  # Cast by species variable and abundance
  # Take just numeric values
  # Assign to commat
  ssdf <- comdf[,colnames(comdf) %in% c(comvar, abundvar, timevar)]
  commat <- spread(data.frame(ssdf), 
                   comvar,
                   abundvar,
                   drop = TRUE,
                   fill = 0)
  
  # Calculate vegetation distance
  vd <- vegdist(commat[,-1], method = "euclidean")
  td <- dist(commat[,colnames(commat) == timevar])
  output <- cbind(interval = c(td), distance = c(vd))
  return(data.frame(output))
}
comp_ratechange <- left_join(long.comp, trtlabels)
Joining, by = c("plot", "block")
comp_ratechange <- comp_ratechange  %>% filter(species %in% waps.specs$Newval[waps.specs$Type != "class"] &
                                        water == "control-2nd" &
                                        sp.trt %in% selected.trts &
                                        clip %in% selected.clips &
                                        fert %in% selected.fert)
temp_ratechange_bray <- data.frame(comp_ratechange) %>% group_by(block, plot, sp.trt, water) %>%
  filter(sp.trt %in% onegroup_trts) %>%
  filter(cover > 0) %>%
  mutate(cover = cover) %>%
  do(calcRateChange_bray(., timevar = "year",
                         comvar = "species",
                         abundvar = "cover"))
ggplot(aes(x = interval,
           y = distance,
           color = sp.trt),
       data = temp_ratechange_bray) +
  geom_point(alpha = .1) +
  facet_wrap(~sp.trt, scales = "fixed") + 
  stat_smooth(method = "lm", se = FALSE)

LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgZGZfcHJpbnQ6IHBhZ2VkDQotLS0NCg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCiMgQ2xlYW5pbmcgdXAgV0FQUyBkYXRhDQpsaWJyYXJ5KGRwbHlyKTtsaWJyYXJ5KHRpZHlyKTtsaWJyYXJ5KHZlZ2FuKTtsaWJyYXJ5KHRlc3R0aGF0KQ0KDQpzZXR3ZCgiQzovVXNlcnMvZWJhdHplci9Cb3ggU3luYy9FdmluZXIgbGFiIHNoYXJlZC9FdmFuL1Jlc2VhcmNoIFByb2plY3RzL1dBUFMgRGF0YSIpDQoNCndhcHMuY29tcCA8LSByZWFkLmNzdigiQzovVXNlcnMvZWJhdHplci9Cb3ggU3luYy9FdmluZXIgbGFiIHNoYXJlZC9FdmFuL1Jlc2VhcmNoIFByb2plY3RzL1dBUFMgRGF0YS9XQVBTdGhyb3VnaDIwMTcuY3N2IiwNCiAgICAgICAgICBoZWFkZXIgPSBUUlVFLA0KICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkNCg0KdHJ0bGFiZWxzIDwtIHJlYWQuY3N2KCJDOi9Vc2Vycy9lYmF0emVyL0JveCBTeW5jL0V2aW5lciBsYWIgc2hhcmVkL0V2YW4vUmVzZWFyY2ggUHJvamVjdHMvV0FQUyBEYXRhL3RydGxhYmVscy5jc3YiLA0KICAgICAgICAgIGhlYWRlciA9IFRSVUUsDQogICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KDQp3YXBzLnNwZWNzIDwtIHJlYWQuY3N2KCJDOi9Vc2Vycy9lYmF0emVyL0JveCBTeW5jL0V2aW5lciBsYWIgc2hhcmVkL0V2YW4vUmVzZWFyY2ggUHJvamVjdHMvV0FQUyBEYXRhL1dBUFNzcGVjaWVzLmNzdiIsIA0KICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzID0gRikNCmBgYA0KDQojIyMgRGF0YSBjbGVhbmluZw0KDQpUaGVyZSBhcmUgYSBidW5jaCBvZiBzbWFsbCBpbmNvbnNpc3RlbmNpZXMgdGhhdCBjb21lIHdpdGggbWFudWFsIGRhdGEgZW50cnkgdGhhdCBuZWVkIHRvIGJlIGNvcnJlY3RlZCBwcmlvciB0byBhbmFseXNpcy4NCg0KX19DaGVja2xpc3Q6X18gIA0KDQoqIENvbnZlcnQgZGF0YXNldCB0byB3aWRlIChtYXRyaXggZm9ybWF0KSBfX2RvbmVfXw0KDQoqIFN0YW5kYXJkaXplIHNwZWNpZXMgbmFtZXMgX19kb25lX18NCg0KKiBDbGVhbiB1cCB5ZWFyIGNvbHVtbiBfX2RvbmVfXw0KDQoqIEFzc2lnbiBOQSBjb3ZlciB2YWx1ZXMgdG8gMCBfX2RvbmVfXw0KDQoqIFN0YW5kYXJkaXplIHRyZWF0bWVudCBsYWJlbHMgX19kb25lX18NCg0KKiBBZGQgImNsYXNzIiBzdGF0aXN0aWNzIHRvIGF0dHJpYnV0ZSB0YWJsZSBfX2RvbmVfXw0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCiMgR2F0aGVycyBkYXRhc2V0IHRvIGxvbmcgZm9ybWF0IGJlZm9yZSBjbGVhbmluZyB1cCwgY3JlYXRlcyBzcGVjaWVzIGNvbHVtbg0KbG9uZy5jb21wIDwtIGdhdGhlcih3YXBzLmNvbXAsIGtleSA9ICJzcGVjaWVzIiwgdmFsdWUgPSAiY292ZXIiLCAtYygxOjcpKQ0KDQojIFJlbW92ZXMgeWVhciBsYWJlbHMgZnJvbSBzcGVjaWVzIGNvbHVtbg0Kc3BlYyA8LSBnc3ViKCJYXFxkXFxkXFwuKiIsICIiLCBsb25nLmNvbXAkc3BlY2llcykNCg0KIyBHcmFicyB0aGUgZmlyc3QgdHdvIGRpZ2l0cyBmcm9tIHRoZSBzcGVjaWVzIGNvbHVtbiB0byBtYWtlIGEgInllYXIiIGNvbHVtbg0KeXIgPC0gZ3N1YignXFwuJywgIiIsIGxvbmcuY29tcCRzcGVjaWVzKQ0KeXIgPC0gZ3N1YigiWCIsICIyMCIsIHlyKQ0KeXIgPC0gZ3N1YigiW1s6YWxwaGE6XV0rMD8iLCAiIiwgeXIpDQoNCiMgUmVhc3NpZ25zIHNwZWNpZXMgdmFyaWFibGUNCmxvbmcuY29tcCRzcGVjaWVzIDwtIHNwZWMNCg0KIyBBdHRhY2hlcyB5ZWFyIHZhcmlhYmxlDQpsb25nLmNvbXAgPC0gY2JpbmQobG9uZy5jb21wLCB5ZWFyID0gYXMubnVtZXJpYyh5cikpDQoNCiMgTG93ZXJjYXNlIG5hbWVzIGZvciBkYXRhc2V0DQpuYW1lcyhsb25nLmNvbXApIDwtIGMoInBsb3QiLCAiYmxvY2siLCAic3ViYmxvY2siLA0KICAgICAgICAgICAgICAgICAgICAgICJ3YXRlciIsICJzcGNvbXAiLCAiZmVydGlsaXphdGlvbiIsDQogICAgICAgICAgICAgICAgICAgICAgImNsaXBwaW5nIiwgInNwZWNpZXMiLCAiY292ZXIiLCAieWVhciIpDQoNCiMgQXNzaWducyBhbGwgTkEgY292ZXIgdmFsdWVzIHRvIHplcm8NCmxvbmcuY29tcCRjb3Zlcltpcy5uYShsb25nLmNvbXAkY292ZXIpXSA8LSAwDQpgYGANCg0KYGBge3J9DQojIFJlYXNzaWducyBzcGVjaWVzIG5hbWVzIHRvIHN0YW5kYXJkaXplZCBuYW1lcyBpbiB0aGUgd2Fwcy5zcGVjcyBkYXRhc2V0DQpmb3IoaSBpbiB3YXBzLnNwZWNzJFNwZWNpZXMpew0KICBsb25nLmNvbXAkc3BlY2llcyA8LSBnc3ViKHBhc3RlKGksICIkIiwgc2VwID0gIiIpLCB3YXBzLnNwZWNzJE5ld3ZhbFt3YXBzLnNwZWNzJFNwZWNpZXMgPT0gaV0sIGxvbmcuY29tcCRzcGVjaWVzKQ0KfQ0KDQojIFJlbW92ZXMgc3BhY2VzIGZyb20gc3BlY2llcyBuYW1lcw0KbG9uZy5jb21wJHNwY29tcCA8LSBnc3ViKCJbWzpzcGFjZTpdXVxcK1tbOnNwYWNlOl1dKiIsICIgXFwrIiwgbG9uZy5jb21wJHNwY29tcCkNCg0KIyBSZW1vdmVzIHdoaXRlc3BhY2UgZnJvbSB0cmVhdG1lbnQgbmFtZXMNCmxvbmcuY29tcCRzcGNvbXAgPC0gZ3N1YigiW1s6c3BhY2U6XV0iLCAiIiwgbG9uZy5jb21wJHNwY29tcCkNCmxvbmcuY29tcCR3YXRlciA8LSBnc3ViKCJbWzpzcGFjZTpdXSIsICIiLCBsb25nLmNvbXAkd2F0ZXIpDQoNCiMgQXNzaWducyBhbGwgTkFzIHRvIHplcm8sIG1lcmdlcyBkdXBsaWNhdGVkIHNwZWNpZXMgbmFtZXMNCmxvbmcuY29tcCRjb3ZlciA8LSBhcy5udW1lcmljKGxvbmcuY29tcCRjb3ZlcikNCmxvbmcuY29tcCRjb3Zlcltpcy5uYShsb25nLmNvbXAkY292ZXIpXSA8LSAwDQpsb25nLmNvbXAgPC0gbG9uZy5jb21wICU+JSBncm91cF9ieShwbG90LCBibG9jaywgc3ViYmxvY2ssIHdhdGVyLCBmZXJ0aWxpemF0aW9uLCBzcGVjaWVzLCB5ZWFyKSAlPiUgc3VtbWFyaXNlKGNvdmVyID0gc3VtKGNvdmVyKSkNCg0KIyBTcHJlYWRzIGRhdGFzZXQgdG8gd2lkZSBmb3JtYXQNCmNvbXAud2lkZSA8LSBzcHJlYWQobG9uZy5jb21wLCBrZXkgPSAic3BlY2llcyIsIHZhbHVlID0gImNvdmVyIikNCmNvbXAuYXR0ciA8LSBzZWxlY3QoY29tcC53aWRlLCBvbmVfb2YoYygieWVhciIsIHdhcHMuc3BlY3MkTmV3dmFsW3dhcHMuc3BlY3MkVHlwZSA9PSAiY2xhc3MiXSkpKQ0KY29tcC53aWRlIDwtIHVuZ3JvdXAoY29tcC53aWRlKSAlPiUgIHNlbGVjdChvbmVfb2Yod2Fwcy5zcGVjcyROZXd2YWxbd2Fwcy5zcGVjcyRUeXBlICE9ICJjbGFzcyJdKSkNCmNvbXAud2lkZSA8LSBhcHBseShjb21wLndpZGUsIDIsIGFzLm51bWVyaWMpDQpjb21wLndpZGVbaXMubmEoY29tcC53aWRlKV0gPC0gMA0KDQojIE1lcmdlcyB3aXRoIHRyZWF0bWVudCBsYWJlbHMNCmNvbXAuYXR0ciA8LSBsZWZ0X2pvaW4oY29tcC5hdHRyLCB0cnRsYWJlbHMpDQpjb21wLmF0dHIkc3AudHJ0IDwtIGdzdWIoIltbOnNwYWNlOl1dIiwgIiIsIGNvbXAuYXR0ciRzcC50cnQpDQpgYGANCg0KQWZ0ZXIgY2xlYW5pbmcsIHdlIG5vdyBoYXZlIHR3byBzZXBhcmF0ZSBkYXRhZnJhbWVzLCBvbmUgdGhhdCBjb3JyZXNwb25kcyB0byBkaWZmZXJlbnQgcGxvdCB0cmVhdG1lbnRzL2xhYmVscyBhbmQgYW5vdGhlciB0aGF0IGNvcnJlc3BvbmRzIHRvIHNwZWNpZXMgYWJ1bmRhbmNlczoNCg0KYGBge3J9DQpoZWFkKGNvbXAuYXR0cilbLDE6MTBdDQpoZWFkKGNvbXAud2lkZSlbLDE6MTBdDQpgYGANCg0KVGhlIHNwZWNpZXMgbWF0cml4IGNvbnRhaW5zIGEgdG90YWwgb2YgNTAgdW5pcXVlIHNwZWNpZXMuIFRoZSBmdWxsIGxpc3QgaXMgcHJvdmlkZWQgYmVsb3c6DQpgYGB7cn0NCmNvbG5hbWVzKGNvbXAud2lkZSkNCmBgYA0KDQoNCiMgT3JkaW5hdGlvbiBhbmFseXNpcw0KDQpgYGB7cn0NCm9uZWdyb3VwX3RydHMgPSBjKCJhbm51YWxzIiwgIldBUFMiLCAiTmF0aXZlcyIpDQptdWx0aWdyb3VwX3RydHMgPSBjKCJuYXRpdmVzK1dBUFMrYW5udWFscyIsICJhbm51YWxzK25hdGl2ZXMiLCAiV0FQUythbm51YWxzIiwgIldBUFMrbmF0aXZlcyIsICJDZW50YXVyZWFzb2xzdGl0aWFsaXMrV0FQUythbm51YWxzIikNCm9uZXNwZWNfdHJ0cyA9IHVuaXF1ZShjb21wLmF0dHIkc3AudHJ0KVshdW5pcXVlKGNvbXAuYXR0ciRzcC50cnQpICVpbiUgYyhvbmVncm91cF90cnRzLCBtdWx0aWdyb3VwX3RydHMpXQ0KDQpzZWxlY3RlZC50cnRzIDwtIGMob25lZ3JvdXBfdHJ0cykNCnNlbGVjdGVkLmNsaXBzIDwtIGMoIm5vbmUiKQ0Kc2VsZWN0ZWQuZmVydCA8LSBjKCJub25lIikNCnNlbGVjdGVkLndhdGVyIDwtIGMoImNvbnRyb2wtMm5kIikgDQoNCm9yZC5tYXQgPC0gY29tcC53aWRlW2NvbXAuYXR0ciR3YXRlciA9PSBzZWxlY3RlZC53YXRlciAmDQogICAgICAgICAgICAgICAgICAgICBjb21wLmF0dHIkc3AudHJ0ICVpbiUgc2VsZWN0ZWQudHJ0cyAmDQogICAgICAgICAgICAgICAgICAgICBjb21wLmF0dHIkY2xpcCAlaW4lIHNlbGVjdGVkLmNsaXBzJg0KICAgICAgICAgICAgICAgICAgICAgY29tcC5hdHRyJGZlcnQgJWluJSBzZWxlY3RlZC5mZXJ0LF0NCg0Kb3JkLmF0dCA8LSBjb21wLmF0dHJbY29tcC5hdHRyJHdhdGVyID09IHNlbGVjdGVkLndhdGVyICYNCiAgICAgICAgICAgICAgICAgICAgIGNvbXAuYXR0ciRzcC50cnQgJWluJSBzZWxlY3RlZC50cnRzICYNCiAgICAgICAgICAgICAgICAgICAgIGNvbXAuYXR0ciRjbGlwICVpbiUgc2VsZWN0ZWQuY2xpcHMgJg0KICAgICAgICAgICAgICAgICAgICAgY29tcC5hdHRyJGZlcnQgJWluJSBzZWxlY3RlZC5mZXJ0LF0NCg0KZXhwZWN0X3RydWUobnJvdyhvcmQuYXR0KSA9PSBucm93KG9yZC5tYXQpKQ0KDQojIEEgbnVtYmVyIG9mIHJvd3MgaGF2ZSBubyByZWNvcmRlZCBsaXZlIHBsYW50cyAobm90IHMpDQpvcmQuYXR0IDwtIG9yZC5hdHRbcm93U3VtcyhvcmQubWF0KSAhPSAwLCBdDQpvcmQubWF0IDwtIG9yZC5tYXRbcm93U3VtcyhvcmQubWF0KSAhPSAwLCBdDQpvcmQubWF0IDwtIHNxcnQob3JkLm1hdCkNCg0KZGlzdG1hdCA8LSB2ZWdkaXN0KG9yZC5tYXQpDQpXQVBTLm1kcyA8LSBtZXRhTURTKGRpc3RtYXQsIHRyeSA9IDUsIHRyeW1heCA9IDUwLCB0cmFjZSA9IEYpDQpNRFNfeHkgPC0gY2JpbmQoZGF0YS5mcmFtZShvcmQuYXR0KSwgZGF0YS5mcmFtZShYID0gV0FQUy5tZHMkcG9pbnRzWywxXSwgWSA9IFdBUFMubWRzJHBvaW50c1ssMl0pKQ0KDQojV0FQUy5wY2EgPC0gcHJjb21wKG9yZC5tYXQpDQojUENBX3h5IDwtIGNiaW5kKGRhdGEuZnJhbWUob3JkLmF0dCksIGRhdGEuZnJhbWUoWCA9IFdBUFMucGNhJHhbLDFdLCBZID0gV0FQUy5wY2EkeFssMl0pKQ0KYGBgDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KZ2dwbG90KE1EU194eSwgYWVzKFgsIFksIGNvbG9yID0gc3AudHJ0LCBzaGFwZSA9IGNsaXApKSArIGdlb21fcG9pbnQoKSArIHRoZW1lX2J3KCkgKyBmYWNldF93cmFwKH55ZWFyKQ0KYGBgDQpgYGB7cn0NCmdncGxvdChNRFNfeHlbb3JkZXIoTURTX3h5JHllYXIpLF0sIGFlcyhYLCBZLCBjb2xvciA9IGFzLmZhY3RvcihwbG90KSkpICsgDQogIGdlb21fcG9pbnQoKSArIA0KICBnZW9tX3BhdGgoIGFycm93ID0gYXJyb3codW5pdCgwLjMwLCJjbSIpLCBhbmdsZSA9IDE1LCBlbmRzID0gImxhc3QiLCB0eXBlID0gImNsb3NlZCIpLCBhbHBoYSA9IC41KSArIA0KICB0aGVtZV9idygpICsgDQogIGZhY2V0X2dyaWQoc3AudHJ0IH4gYmxvY2spICsNCiAgZ3VpZGVzKGNvbG9yID0gRkFMU0UpDQoNCmBgYA0KYGBge3J9DQpncm91cF9hYnVuZCA8LSBNRFNfeHkgJT4lIGdhdGhlcihrZXkgPSAiZ3JvdXAiLCB2YWx1ZSA9ICJjb3ZlciIsIGFubnVhbHMsIGJhcmUsIHdhcHMsIG5hdGl2ZXMsIHdlZWRzKSAlPiUNCiAgcmVwbGFjZV9uYShsaXN0KGNvdmVyID0gMCkpIA0KDQpnZ3Bsb3QoZGF0YSA9IGdyb3VwX2FidW5kLCANCiAgICAgICBhZXMoeCA9IHllYXIsDQogICAgICAgICAgIHkgPSBjb3ZlciwNCiAgICAgICAgICAgY29sb3IgPSBncm91cCkpICsNCiAgZ2VvbV9wb2ludCgpICsgDQogIGZhY2V0X3dyYXAofnNwLnRydCkgKw0KICBzdGF0X3Ntb290aChtZXRob2QgPSAibG0iKQ0KDQoNCmBgYA0KDQoNCmBgYHtyfQ0KY2FsY1JhdGVDaGFuZ2VfYnJheSA8LSBmdW5jdGlvbihjb21kZiwgY29tdmFyLCBhYnVuZHZhciwgdGltZXZhcil7DQogICMgVGFrZSBkYXRhZnJhbWUsDQogICMgQ2FzdCBieSBzcGVjaWVzIHZhcmlhYmxlIGFuZCBhYnVuZGFuY2UNCiAgIyBUYWtlIGp1c3QgbnVtZXJpYyB2YWx1ZXMNCiAgIyBBc3NpZ24gdG8gY29tbWF0DQogIHNzZGYgPC0gY29tZGZbLGNvbG5hbWVzKGNvbWRmKSAlaW4lIGMoY29tdmFyLCBhYnVuZHZhciwgdGltZXZhcildDQogIGNvbW1hdCA8LSBzcHJlYWQoZGF0YS5mcmFtZShzc2RmKSwgDQogICAgICAgICAgICAgICAgICAgY29tdmFyLA0KICAgICAgICAgICAgICAgICAgIGFidW5kdmFyLA0KICAgICAgICAgICAgICAgICAgIGRyb3AgPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgIGZpbGwgPSAwKQ0KICANCiAgIyBDYWxjdWxhdGUgdmVnZXRhdGlvbiBkaXN0YW5jZQ0KICB2ZCA8LSB2ZWdkaXN0KGNvbW1hdFssLTFdLCBtZXRob2QgPSAiZXVjbGlkZWFuIikNCiAgdGQgPC0gZGlzdChjb21tYXRbLGNvbG5hbWVzKGNvbW1hdCkgPT0gdGltZXZhcl0pDQogIG91dHB1dCA8LSBjYmluZChpbnRlcnZhbCA9IGModGQpLCBkaXN0YW5jZSA9IGModmQpKQ0KICByZXR1cm4oZGF0YS5mcmFtZShvdXRwdXQpKQ0KfQ0KDQpjb21wX3JhdGVjaGFuZ2UgPC0gbGVmdF9qb2luKGxvbmcuY29tcCwgdHJ0bGFiZWxzKQ0KDQpjb21wX3JhdGVjaGFuZ2UgPC0gY29tcF9yYXRlY2hhbmdlICAlPiUgZmlsdGVyKHNwZWNpZXMgJWluJSB3YXBzLnNwZWNzJE5ld3ZhbFt3YXBzLnNwZWNzJFR5cGUgIT0gImNsYXNzIl0gJg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhdGVyID09ICJjb250cm9sLTJuZCIgJg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwLnRydCAlaW4lIHNlbGVjdGVkLnRydHMgJg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsaXAgJWluJSBzZWxlY3RlZC5jbGlwcyAmDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVydCAlaW4lIHNlbGVjdGVkLmZlcnQpDQoNCg0KdGVtcF9yYXRlY2hhbmdlX2JyYXkgPC0gZGF0YS5mcmFtZShjb21wX3JhdGVjaGFuZ2UpICU+JSBncm91cF9ieShibG9jaywgcGxvdCwgc3AudHJ0LCB3YXRlcikgJT4lDQogIGZpbHRlcihzcC50cnQgJWluJSBvbmVncm91cF90cnRzKSAlPiUNCiAgZmlsdGVyKGNvdmVyID4gMCkgJT4lDQogIG11dGF0ZShjb3ZlciA9IGNvdmVyKSAlPiUNCiAgZG8oY2FsY1JhdGVDaGFuZ2VfYnJheSguLCB0aW1ldmFyID0gInllYXIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXZhciA9ICJzcGVjaWVzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICBhYnVuZHZhciA9ICJjb3ZlciIpKQ0KDQpnZ3Bsb3QoYWVzKHggPSBpbnRlcnZhbCwNCiAgICAgICAgICAgeSA9IGRpc3RhbmNlLA0KICAgICAgICAgICBjb2xvciA9IHNwLnRydCksDQogICAgICAgZGF0YSA9IHRlbXBfcmF0ZWNoYW5nZV9icmF5KSArDQogIGdlb21fcG9pbnQoYWxwaGEgPSAuMSkgKw0KICBmYWNldF93cmFwKH5zcC50cnQsIHNjYWxlcyA9ICJmaXhlZCIpICsgDQogIHN0YXRfc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UpDQoNCmBgYA0KYGBge3J9DQpzdW1tYXJ5KGxtKGRpc3RhbmNlIH4gaW50ZXJ2YWwgKiBzcC50cnQsIGRhdGEgPSB0ZW1wX3JhdGVjaGFuZ2VfYnJheSkpDQoNCnBsb3QobG0oZGlzdGFuY2UgfiBpbnRlcnZhbCAqIHNwLnRydCwgZGF0YSA9IHRlbXBfcmF0ZWNoYW5nZV9icmF5KSkNCmBgYA0KDQoNCg==